﻿#ifdef xxx
#include "test.h"
#include <initializer_list>
#include <hashtable.h>
#include <unordered_map>
#include <ctime>
#include <ratio>
#include <chrono>
#include <memory>
#include <list>
#ifdef __linux__
#include <ucontext.h>
#endif
#include <unistd.h>
//#include <bits/stl_tree.h>
#include "event/event_reporter.h"
#include "event/event_reporter_manager.h"
#include <sys/time.h>
#include <atomic>
#include <mutex>
#include <queue>
#include "thread/thread_pool.h"
#include "net/socket_op.h"
#include "common/os/time.h"
#include "dep/fmt/include/fmt/format.h"
#include "dep/fmt/include/fmt/color.h"
#include "coroutine/coroutine.h"
#include "redis/redis_client.h"
#include "common/container/details/rb_tree_test_1.h"
#include "common/container/set.h"


TestC::~TestC()
{
    if (worker_thread_ && worker_thread_->joinable())
    {
        worker_thread_->join();
    }
    delete worker_thread_;
    worker_thread_ = nullptr;
}

void TestC::test_rect()
{
    UtilMath::Init();

    TargetScope scope;
    scope.range_far = 5.6;
    scope.angle = 1.5;
    scope.forward = Vector3(-1, 0, 1);
    scope.position = Vector3::zero;

    //for (auto &p: check_pos)
    for (int i = 0; i < 100; ++i)
    {
        Vector3 p = Vector3::zero;
        p.SetZ(std::rand() % 10);
        p.SetX(std::rand() % 10);
        auto res = IsInRange(scope, p, 0);
        //std::cout << p.ToString() << " -> " << res.first << " " << res.second << "\n";
    }
    return;

    float radius = 0.0f;
    float w = 4;
    float d = 2;
    float hw = w / 2.0f + radius;
    float hd = d / 2.0f + radius;
    const Vector3 &forward = Vector3::forward;
    Vector3 pos = Vector3(-2, 0, 1.9);
    Vector3 center = Vector3(-2, 0, 0);

    float fowardRot = Vector3::Angle(Vector3::forward, forward);
    if (!Vector3::Clockwise(Vector3::forward, forward))
        fowardRot = -fowardRot;
    std::cout << fowardRot << "\n";

    Vector3 vecs[4];
    vecs[0].Set(-hw, 0, -hd);
    vecs[1].Set(-hw, 0, hd);
    vecs[2].Set(hw, 0, hd);
    vecs[3].Set(hw, 0, -hd);

    // for (int32_t i = 0; i < 4; ++i)
    // {
    //     std::cout << vecs[i].ToString() << "\n";
    // }
    std::cout << (UtilMath::IsInRect(pos, vecs, center, fowardRot) ? 1 : 0) << "\n";

    fowardRot = Vector3::Angle(Vector3::left, forward);
    if (!Vector3::Clockwise(Vector3::forward, forward))
        fowardRot = -fowardRot;
    std::cout << fowardRot << "\n";

    std::cout << (UtilMath::IsInRect(pos, vecs, center, fowardRot) ? 1 : 0) << "\n";
}

void TestC::test_fork()
{
    pid_t pid;
    printf("befor: pid is %d\n", getpid());
    //if((pid = fork()) == -1)
    {
        perror("fork()");
    }
    printf("After:pid is %d,fork return %d\n", getpid(), pid);
    sleep(1);
}

void TestC::test_pointer()
{
    int i = 0, *p = &i;
    //printf("step 1: i=%d, &i=%d, p=%d *p=%d\n", i, &i, p, *p);
    *p++;
    //printf("step 3: i=%d, &i=%d, p=%d *p=%d\n", i, &i, p, *p);
    (*p)++;
    //printf("step 2: i=%d, &i=%d, p=%d *p=%d\n", i, &i, p, *p);
    //printf("step 4: p - &i=%d\n", p - &i);
}

void TestC::test_template_template_parameter()
{
    XCls<std::string, Vec> c1;
    XCls<std::string, List> c2;
}

void TestC::test_lambda()
{
    auto cmp = [](int a, int b) {
        return true;
    };
    //  lambda没有默认构造函数和默认复制构造函数
    std::set<int, decltype(cmp)> test_set(cmp);
    test_set.insert(2);
    test_set.insert(1);
    test_set.insert(3);

    std::map<std::string, int> coll = {{"a", 1}, {"b", 2}, {"c", 3}};
    int sum = std::accumulate(coll.begin(), coll.end(),
                              0,
                              std::bind(std::plus<int>(),
                                        std::placeholders::_1,
                                        std::bind(&std::map<std::string, int>::value_type::second,
                                                  std::placeholders::_2)));
    std::cout << sum << std::endl;

    int sum2 = std::accumulate(coll.begin(), coll.end(),
                               0, [](int a, std::map<std::string, int>::value_type b) -> int {
                                   return a + b.second * 2;
                               });
    std::cout << sum2 << std::endl;
}

void TestC::test_tuple()
{
    Tuple<int32_t, std::string, char, float> tp(0, "cba", 'd', 1.012);
    std::cout << tp.head() << " "
              << tp.tail().head() << " "
              << tp.tail().tail().head() << " "
              << tp.tail().tail().tail().head() << std::endl;
}

struct EmptyStruct
{
};

struct eqstr
{
    bool operator()(const char s1, const char s2) const
    {
        // return strcmp(s1, s2) == 0;
        return s1 == s2;
    }
};

void TestC::test_container()
{
    std::function<void(void)> func = []() -> void {};
    std::map<char, char> mp;
    std::set<char> st;

    std::cout << "sizeof(std::function<void(void)>)=" << sizeof(std::function<void(void)>) << std::endl;
    std::cout << "sizeof(func)=" << sizeof(func) << std::endl;

    std::cout << "sizeof(std::map<char, char>)=" << sizeof(std::map<char, char>) << std::endl;
    std::cout << "sizeof(std::set<char>)=" << sizeof(std::set<char>) << std::endl;

    std::_Rb_tree<int32_t, int32_t, std::_Identity<int32_t>, std::less<int32_t>> rb;

    std::cout << "sizeof(_Rb_tree_color)=" << sizeof(std::_Rb_tree_color::_S_black) << std::endl;

    std::cout << "sizeof(_Rb_tree<...>)=" << sizeof(rb) << std::endl;

    auto it = rb._M_insert_equal(1);
    it = rb._M_insert_equal(1);
    std::cout << *it << std::endl;
    std::cout << rb.size() << std::endl;
    auto p = rb._M_insert_unique(1);
    std::cout << p.second << std::endl;

    std::unordered_set<int32_t> un_st;
    un_st.insert(0);
    std::cout << "bucket_size(0)=" << un_st.bucket_size(0) << std::endl;

    std::cout << "sizeof(EmptyStruct)=" << sizeof(EmptyStruct) << std::endl;

    // std::__uset_hashtable<char,
    //                 std::hash<char>,
    //                 eqstr,
    //                 char,
    //                 std::allocator<char>> ht;

    // std::hash<std::string>();
    std::unordered_map<int32_t, std::string> ump;
    const auto uit = ump.find(1);
}

void TestC::test_cplusplus()
{
    std::cout << __cplusplus << std::endl;
}

void XXX()
{
    std::cout << "XXX" << std::endl;
}

void TestC::test_func()
{
    std::cout << __func__ << std::endl;
    // 在源代码中插入当前源代码行号
    std::cout << __LINE__ << std::endl;
    // 在源文件中插入当前源文件名
    std::cout << __FILE__ << std::endl;
    // 在源文件中插入当前的编译日期
    std::cout << __DATE__ << std::endl;
    // 在源文件中插入当前编译时间
    std::cout << __TIME__ << std::endl;
    // 当要求程序严格遵循ANSI C标准时该标识被赋值为1
    std::cout << __STDC__ << std::endl;
    // 当编写C++程序时该标识符被定义
    std::cout << __cplusplus << std::endl;

    std::function<void()> func = XXX;
    std::cout << func.target_type().name() << std::endl;
}

void TestC::test_erase_98()
{
    std::map<int32_t, int32_t> mp;
    int32_t cnt = 100000000;
    while (cnt--)
    {
        int32_t r = std::rand();
        mp.emplace(r, r);
    }

    //std::time_t start = std::time(NULL);
    //clock_t start,end;
    //start=clock();

    auto t1 = std::chrono::steady_clock::now();
    //run code
    for (auto it = mp.begin(); it != mp.end();)
    {
        //std::cout << "erase " << it->first << std::endl;
        mp.erase(it++);
    }
    //std::cout << "[std::map::erase] time passed: " << std::difftime(std::time(NULL), start) << " s.\n";
    //std::cout << ::GetTickCount() - k << std::endl;
    //end=clock();
    //printf("time=%f\n",(float)(end-start)*1000/CLOCKS_PER_SEC);
    auto t2 = std::chrono::steady_clock::now();
    double dr_ms = std::chrono::duration<double, std::milli>(t2 - t1).count();
    std::cout << dr_ms << std::endl;

    std::cout << "erase 98 end" << std::endl;
}

void TestC::test_erase_11()
{
    std::map<int32_t, int32_t> mp;
    int32_t cnt = 100000000;
    while (cnt--)
    {
        int32_t r = std::rand();
        mp.emplace(r, r);
    }

    //std::time_t start = std::time(NULL);
    //clock_t start,end;
    //start=clock();

    auto t1 = std::chrono::steady_clock::now();
    //run code
    for (auto it = mp.begin(); it != mp.end();)
    {
        //std::cout << "erase " << it->first << std::endl;
        //mp.erase(it++);
        it = mp.erase(it);
    }
    //std::cout << "[std::map::erase] time passed: " << std::difftime(std::time(NULL), start) << " s.\n";
    //std::cout << ::GetTickCount() - k << std::endl;
    //end=clock();
    //printf("time=%f\n",(float)(end-start)*1000/CLOCKS_PER_SEC);
    auto t2 = std::chrono::steady_clock::now();
    double dr_ms = std::chrono::duration<double, std::milli>(t2 - t1).count();
    std::cout << dr_ms << std::endl;

    std::cout << "erase 11 end" << std::endl;
}

void TestC::test_distance()
{
    float current_target_des_x_ = 137;
    float current_target_des_z_ = 178.92;
    float cur_pos_x = 136.9;
    float cur_pos_z = 179.48;
    float distance = (current_target_des_x_ - cur_pos_x) * (current_target_des_x_ - cur_pos_x) + (current_target_des_z_ - cur_pos_z) * (current_target_des_z_ - cur_pos_z);
    distance = sqrt(distance);
    std::cout << distance;
    if (distance < 0.7f)
    {
        //小于一步,认为已经抵达
        std::cout << " < 0.7f" << std::endl;
    }
    else
    {
        std::cout << " > 0.7f" << std::endl;
    }
}

void TestC::test_fill()
{
    // RangeFill range(15, 1);
    // std::vector<Vector3> polygon;
    // polygon.emplace_back(1, 0, 1);
    // polygon.emplace_back(10, 0, 1);
    // polygon.emplace_back(10, 0, 3);
    // polygon.emplace_back(1, 0, 3);
    // range.Fill(polygon);
    // range.Remove(0);

    RangeFill range(20, 0.5);
    std::vector<Vector3> polygon;
    polygon.emplace_back(1, 0, 1);
    polygon.emplace_back(2.6f, 0, 2.1f);
    polygon.emplace_back(5.2f, 0, 1.5f);
    polygon.emplace_back(6.7f, 0, 2.3f);
    polygon.emplace_back(5.4f, 0, 3.4f);
    polygon.emplace_back(2.4f, 0, 4.5f);
    range.Fill(polygon);
    Vector3 result = Vector3::zero;
    if (range.Query(Vector3(3, 0, 3), result))
    {
        std::cout << result.ToString() << std::endl;
    }
    range.Remove(0);

    // RangeFill range(15, 1);
    // Vector3 center(5, 0, 5);
    // float r1 = 1.0f;
    // float r2 = 4.0f;
    // range.Fill(center, r1, r2);
    // range.Remove(0);
    TemplateAlgo<FieldData>();
}

void TestC::test_smart_ptr()
{
    std::shared_ptr<TestC> shared_test = std::make_shared<TestC>();
    auto shared_test2 = shared_test;
    // shared_test2.reset();
    if (shared_test.get())
    {
        std::cout << "not null" << std::endl;
    }
    shared_test.reset();
    auto *p = shared_test2.get();
    if (p)
    {
        // delete p;
    }
    shared_test2.get()->test_cplusplus();
}

void TestC::test_event()
{
    EventReporterManager::CreateInstance();
    {
        for (int32_t i = 0; i < 100; ++i)
        {
            EventCallReporter reporter;
            reporter.obj = this;
            reporter.event_call_info.emplace(EventCallReporter::KeyType(__FILE__, 2), EventCallData(0, 1));
            reporter.event_call_info.emplace(EventCallReporter::KeyType("map.cpp", 6), EventCallData(1, 1));
            reporter.event_call_info[EventCallReporter::KeyType("map.cpp", 6)] += 1;

            EventCallReporter reporter2;
            reporter2.obj = this;
            reporter2.event_call_info[EventCallReporter::KeyType(__FILE__, 2)].event_type = 0;
            reporter2.event_call_info[EventCallReporter::KeyType(__FILE__, 2)] += 1;

            reporter2.event_call_info[EventCallReporter::KeyType("map.cpp", 6)].event_type = 1;
            reporter2.event_call_info[EventCallReporter::KeyType("map.cpp", 6)] += 2;
        }
    }
    EventReporterManager::Instance()->Dump(this);
    EventReporterManager::DestroyInstance();
}

void TestC::test_typeid()
{
    std::cout << typeid(this).name() << " " << typeid(this).hash_code() << std::endl;
}

void TestC::test_readwritequeue()
{
    auto *tlog = new TargetScope;
    if (!tlog_send_queue_.enqueue(tlog))
    {
        delete tlog;
        tlog = nullptr;
    }
    /*
    worker_thread_ = new std::thread([this]()
    {
        TargetScope* rolog = nullptr;
        while (tlog_send_queue_.try_dequeue(rolog))
        {
            std::cout << rolog->position.ToString().c_str() << std::endl;
            delete rolog;
        }
    });
    */
}

void TestC::test_list()
{
    std::list<std::string> str_list{"ddd", "eee"};
    std::list<std::string> tmp_list{"aaa", "bbb", "ccc"};
    std::map<int32_t, std::string *> weight_list;
    int32_t i = 0;
    for (auto &it : tmp_list)
    {
        weight_list[i++] = &it;
    }

    for (auto &it : weight_list)
    {
        std::cout << it.first << " " << it.second << " " << *it.second << std::endl;
    }

    str_list.splice(str_list.end(), tmp_list);

    for (auto &it : weight_list)
    {
        std::cout << it.first << " " << it.second << " " << *it.second << std::endl;
    }

    for (auto &it : str_list)
    {
        std::cout << it << " " << &it << std::endl;
    }
}

void TestC::test_ucontext()
{
    printf("Hello world\n");
#ifdef __linux__
    ucontext_t context;

    //获取当前程序上下文
    getcontext(&context);
    printf("Hello world\n");
    sleep(1);
    //将程序切换至context指向的上下文处
    setcontext(&context);
#endif
}

void TestC::test_thread()
{
    std::cout << "hardware concurrency: " << std::thread::hardware_concurrency() << std::endl;
    std::thread thread([](int i, const std::string &s) {
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        std::cout << i << " " << s << std::endl;
    }, 123, "hello world");
    thread.detach();
    assert(!thread.joinable());
}

void TestC::test_parallel_accumulate()
{
    std::vector<int32_t> vec(1000000, 1);
    std::accumulate(vec.begin(), vec.end(), 1);
    //for (auto &it: vec)
    {
        //std::cout << it << " ";
    }
    //std::cout << std::endl;
    int32_t init = 0;
    int32_t result = parallel_accumulate(vec.begin(), vec.end(), init);
    //for (auto &it: vec)
    {
        //std::cout << it << " ";
    }
    std::cout << "result=" << result << std::endl;
}

void TestC::test_gettimeofday()
{
    struct timeval tv;
    struct timezone tz;
    gettimeofday(tv, tz);
    std::cout << "tv_sec: " << tv.tv_sec << std::endl;

    std::cout << "tv_usec:" << tv.tv_usec << std::endl;

    std::cout << "tz_minuteswest: " << tz.tz_minuteswest << std::endl;

    std::cout << "tz_dsttime: " << tz.tz_dsttime << std::endl;
}

void TestC::test_uniqueptr(RoleInfo *raw_ptr)
{
    std::cout << std::string(__func__) << std::endl;

    std::unique_ptr<RoleInfo> uptr(raw_ptr);
    std::cout << raw_ptr->x << " " << raw_ptr->y << std::endl;
    inner_test_uniqueptr(*uptr.get());
}
void TestC::inner_test_uniqueptr(const RoleInfo &role_info)
{
    std::cout << std::string(__func__) << std::endl;
    std::cout << role_info.x << " " << role_info.y << std::endl;
}

std::atomic_flag lock = ATOMIC_FLAG_INIT;

void f(int n)
{
    for (int cnt = 0; cnt < 3; ++cnt)
    {
        while (lock.test_and_set(std::memory_order_acquire)) // 获得锁
            ;                                                // 自旋
        std::cout << "Output from thread " << n << '\n';
        lock.clear(std::memory_order_release); // 释放锁
    }
}

void TestC::test_atomic()
{
    std::mutex m_mutex;
    std::unique_lock<std::mutex> lock(m_mutex);
    lock.unlock();
    std::vector<std::thread> v;
    for (int n = 0; n < 10; ++n)
    {
        v.emplace_back(f, n);
    }
    for (auto &t : v)
    {
        t.join();
    }
}

void Run()
{
    //std::cout << "Run" << std::endl;
}

void TestC::test_thread_pool()
{
    thread_pool pool;
    std::cout << "TestC::test_thread_pool.Start" << std::endl;
    size_t thread_num = 3;
    pool.start(thread_num);

    std::this_thread::sleep_for(std::chrono::milliseconds(10));
    for (int32_t i = 0; i < 100; ++i)
    {
        //std::this_thread::sleep_for(std::chrono::milliseconds(100));
        //pool.AddValue();
        pool.add_task([i]() {
            std::this_thread::sleep_for(std::chrono::milliseconds(1000));
            printf("i=%d\n", i);
        });
        //std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }

    std::this_thread::sleep_for(std::chrono::milliseconds(5000));
    std::cout << "TestC::test_thread_pool.Stop" << std::endl;
}

void TestC::test_socket()
{
    std::cout << os::get_seconds_since_epoch()
              << std::endl;

    auto sockfd = SocketOp::create(0);
    //SocketOp::connect(sockfd, ..)
    char buf[10] = "Hello";
    SocketOp::write(sockfd, buf, sizeof(buf));
    SocketOp::close(sockfd);

    SocketOp::socket_t fds[2];
    SocketOp::socketpair(fds);

    std::cout << "main pid=" << getpid() << std::endl;
    if (fork())
    { /* 父进程 */
        int val = 0;
        close(fds[1]);
        while (1)
        {
            //sleep(5);
            //++val;
            //write(fds[0], &val, sizeof(val));
            //printf("pid=%d 发送数据: %d\n", getpid(), val);

            read(fds[0], &val, sizeof(val));
            printf("pid=%d 接收数据: %d\n", getpid(), val);
        }
    }
    else
    { /*子进程*/
        int val = 0;
        close(fds[0]);
        while (1)
        {
            sleep(5);

            //read(fds[1], &val, sizeof(val));
            //printf("pid=%d 接收数据: %d\n", getpid(), val);

            ++val;
            write(fds[1], &val, sizeof(val));
            //printf("pid=%d 发送数据: %d\n", getpid(), val);
        }
    }

    std::cout << os::get_seconds_since_epoch()
              << std::endl;
}

void TestC::test_suduku(std::vector<int32_t> vec, size_t curr_index, int32_t value)
{ // 把-1填充0或1，使得1和0数量相等，有几种方法
    vec[curr_index] = value;
    for (size_t i = curr_index + 1; i < vec.size(); ++i)
    {
        if (vec[i] == -1)
        {
            test_suduku(vec, i, 0);
            test_suduku(vec, i, 1);
            return;
        }
    }
    uint32_t cnt_zero = 0;
    uint32_t cnt_one = 0;
    for (size_t i = 0; i < vec.size(); ++i)
    {
        if (vec[i] == -1)
        {
            return;
        }
        if (i >= 2)
        {
            if (vec[i] == vec[i - 1] && vec[i - 1] == vec[i - 2])
            {
                return;
            }
        }
        vec[i] == 0 ? cnt_zero++ : cnt_one++;
    }
    if (cnt_one == cnt_zero)
    {
        for (size_t i = 0; i < vec.size(); ++i)
        {
            printf("%d", vec[i]);
        }
        printf("\n");
    }
}

void TestC::test_priority_queue()
{
    std::priority_queue<int32_t,
                        std::vector<int32_t>,
                        std::greater<int32_t>>
        pq;
    std::size_t k = 3;
    for (int32_t i = 0; i < 1000; ++i)
    {
        pq.emplace(i);
        if (pq.size() > k)
        {
            pq.pop();
        }
    }
    while (!pq.empty())
    {
        int32_t x = pq.top();
        pq.pop();
        //printf("rank:%u,x:%d\n", k, x);
        k--;
    }
}

void TestC::test_money()
{
    float base_money = 30;
    float percent = 0.0f;
    float salary = 2.3f;
    float salary_taken = 0.4;
    float real_salary_money = salary - salary_taken;
    float used_money = 0;
    float now_money = base_money;
    int win = 1;

    srand(time(nullptr));
    for (int32_t year = 1; year <= 10; ++year)
    {
        if (year % 2 == 0)
        {
            salary += 0.2;
            salary_taken *= 1.2;
            real_salary_money = salary - salary_taken;
        }
        float tmp = now_money;
        for (int32_t month = 1; month <= 12; ++month)
        {
            for (int32_t day = 1; day <= 30; ++day)
            {
                if (day % 7 == 0)
                {
                    now_money -= 0.03;
                }
                if (month % 3 == 0 && day == 22)
                {
                    now_money -= 0.87;
                }
                if (day == 30)
                {
                    now_money -= 0.3;
                }
                // now_money -= used_money;
            }

            //printf("#month:%d percent:%.2f\n", month, percent);
            percent = 0.04;
            {
                now_money = (now_money * 0.20f) * (1.0f + percent) + (now_money * 0.8) * (1 + 0.02f);
            }
            now_money += real_salary_money;
        }
        now_money += real_salary_money * 2;

        printf("#year:%d salary:%.2f add:%.2f now:%.2f\n", year, salary, now_money - tmp, now_money);
    }
}

void TestC::test_time()
{
    std::cout << "now_time_point=" << (os::now_time_point().time_since_epoch().count()) << std::endl;
    os::tm_t t = os::localtime();
    printf("localtime: y:%d m:%d d:%d s:%d\n", t.tm_year, t.tm_mon, t.tm_mday, t.tm_sec);
    t = os::gmtime();
    printf("gmtime: y:%d m:%d d:%d s:%d\n", t.tm_year, t.tm_mon, t.tm_mday, t.tm_sec);
}

std::mutex m;
std::condition_variable cv;
std::string data;
bool ready = false;
bool processed = false;
 
void worker_thread()
{
    // 等待直至 main() 发送数据
    std::unique_lock<std::mutex> lk(m);
    cv.wait(lk, []{return ready;});
 
    // 等待后，我们占有锁。
    std::cout << "Worker thread is processing data\n";
    data += " after processing";
 
    // 发送数据回 main()
    processed = true;
    std::cout << "Worker thread signals data processing completed\n";
 
    // 通知前完成手动解锁，以避免等待线程才被唤醒就阻塞（细节见 notify_one ）
    lk.unlock();
    cv.notify_one();
}

void TestC::test_condition_variable()
{
    std::thread worker(worker_thread);

    data = "Example data";
    // 发送数据到 worker 线程
    {
        std::lock_guard<std::mutex> lk(m);
        ready = true;
        std::cout << "main() signals data ready for processing\n";
    }
    cv.notify_one();
 
    // 等候 worker
    {
        std::unique_lock<std::mutex> lk(m);
        cv.wait(lk, []{return processed;});
    }
    std::cout << "Back in main(), data = " << data << '\n';
 
    worker.join();
}

void TestC::test_loop()
{
}

void TestC::test_fmt()
{
    fmt::print("hello {}", "world");
    fmt::print(stderr, "System error code = {}\n", errno);
    fmt::print("Don't {}\n", "panic");
    fmt::print("I'd rather be {1} than {0}.\n", "right", "happy");
    fmt::print("Hello, {name}! The answer is {number}. Goodbye, {name}.\n"
        , fmt::arg("name", "World"), fmt::arg("number", 42));
    using namespace fmt::literals;
    fmt::print("Hello, {name}! The answer is {number}. Goodbye, {name}.\n",
           "name"_a="World", "number"_a=42);
    fmt::print(fmt::emphasis::bold | fmt::emphasis::italic | fg(fmt::color::red), "Elapsed time: {0:.2f} seconds\n", 1.23);
    try {
        std::cout << fmt::format("The answer is {:d}", "forty-two") << std::endl;
    }
    catch (std::exception e)
    {
        std::cout << e.what() << std::endl;
        return;
    }
}

int s_id = 0;

class fun_obj {
private:
    std::atomic<int> c{ 0 };
public:
    void operator ()()
    {
        //std::cout << "当前线程id: " << std::this_thread::get_id() << std::endl;
        //printf("#%d start\n", s_id++);
        co_enter(c) {
            while (1) {
            co_yield(__LINE__) printf("#%d c=%d 0\n", s_id++, c.load());
            co_yield(__LINE__) printf("#%d c=%d 1\n", s_id++, c.load());
            co_yield(__LINE__) printf("#%d c=%d 2\n", s_id++, c.load());
            co_yield(__LINE__) printf("#%d c=%d 3\n", s_id++, c.load());
            co_yield(__LINE__) printf("#%d c=%d 4\n", s_id++, c.load());
            }
        }
        //printf("#%d c=%d end\n", s_id++, c);
        return;
    }
};

void TestC::test_co()
{
    test_tmp<std::string>("233");
    //std::cout << "主线程 id：" << std::this_thread::get_id() << std::endl;

    fun_obj f;
    f();

    int x1 = 10;
    std::thread th1([&f, &x1]() { while (x1--) f(); });
    //std::cout << "线程1 id：" <<  th1.get_id() << std::endl;

    int x2 = 10;
    std::thread th2([&f, &x2]() { while (x2--) f(); });
    //std::cout << "线程2 id：" <<  th2.get_id() << std::endl;

    //std::thread th3([&f]() { f(); });
    //std::cout << "线程3 id：" <<  th3.get_id() << std::endl;

    //std::thread th4([&f]() { f(); });
    //std::cout << "线程4 id：" <<  th4.get_id() << std::endl;

    //std::thread th5([&f]() { f(); });

    for (int i = 0; i < 50; ++i)
    {
        f();
    }

    th1.join();
    th2.join();
    //th3.join();
    //th4.join();
    //th5.join();
}


void TestC::test_redis()
{
    redis_client redis_cli;
    //redis_cli.connect("127.0.0.1", 6379);
    redis_cli.connect_ac("127.0.0.1");
    redis_cli.set_ac("HH", "1014");
    std::cout << "HH=" << redis_cli.get_ac("HH") << std::endl;
    std::cout << "del HH=" << redis_cli.del_ac("HH") << std::endl;
}

void TestC::test_rbtree()
{
    //std::cout << sizeof(RBTree<int32_t, int32_t>) << std::endl;
    //std::cout << sizeof(BinNodeBase*) << std::endl;
    //std::cout << sizeof(RBNode<int32_t>*) << std::endl;
    //std::cout << sizeof(std::set<int32_t>) << std::endl;
    //RBTree<int32_t, int32_t> st;
    Set<int32_t> st;
    std::set<int32_t> st2;
    std::multiset<int32_t> mt_st;
    RBTree1<int32_t, int32_t> st3;

    bool test = true;
    if (test)
    {
        do
        {
            srand(time(nullptr));
            std::vector<int32_t> vec = {
                //9,10,7,4,8,6,5,2,3,1
                //41, 81, 94, 45, 66, 27, 56, 96,38,49,40,57,29,76,67,8,72,1,75,97,93,33,28,82,42,34,48,71,70,26,98,22,68,32,99,62,73,65,18,88,64,30,23,74,69,54,59,10,15,92,5,91,19,77,83,14,21,86,50,13,80,51,24,4,43
                //1,4,2,5,3
                //3,1,2,4,6,5
            };
            for (int i = 0; i < 50; ++i)
            {
                vec.emplace_back(rand() % 1000);
            }
            std::sort(vec.begin(), vec.end());
            auto it = std::unique(vec.begin(), vec.end());
            vec.erase(it, vec.end());
            std::random_shuffle(vec.begin(), vec.end());
            for (auto &it : vec)
            {
                st.insert(it);
                st.find(it);
            }
            for (auto &it: vec)
            {
                st2.insert(it);
            }
            std::vector<int32_t> rs;
            for (auto &it : vec)
            {
                int32_t ri = rand() % 10000000;
                rs.emplace_back(ri);
                if (std::find(vec.begin(), vec.end(), ri) == vec.end())
                {
                    st.insert(ri);
                    st2.insert(ri);
                }
                if (*st.begin() != *st2.begin())
                {
                    for (auto &x : vec)
                    {
                        printf("%d,", x);
                    }
                    printf("\n");
                    for (auto &x : rs)
                    {
                        printf("%d,", x);
                    }
                    printf("\n");
                    return;
                }
 
                st.erase(it);
                st2.erase(it);

                if (std::find(vec.begin(), vec.end(), ri) == vec.end())
                {
                    st.erase(ri);
                    st2.erase(ri);
                }
           }
           assert(st.size() == 0);
           assert(st2.size() == 0);
        } while (1);
        return;
    }
    srand(time(nullptr));

    std::vector<uint32_t> test_vec;
    constexpr uint32_t test_cnt = 100;
    uint32_t cnt = test_cnt;
    constexpr uint32_t test_size = 10000000;
    std::vector<int32_t> rand_vec(test_size);
    std::iota(rand_vec.begin(), rand_vec.end(), 1);
    time_t res = 0;
    while (cnt--)
    {
        std::cout << "Test #" << test_cnt - cnt << std::endl;
        std::cout << "prepare random data..." << std::endl;
        
        //st.clear();
        //st2.clear();
        //st3.clear();

        std::random_shuffle(rand_vec.begin(), rand_vec.end());

        std::cout << "start test insert..." << std::endl;
        auto start_time = os::get_milliseconds_since_epoch();
        auto end_time = os::get_milliseconds_since_epoch();
        auto x1 = start_time;
        auto x2 = x1;
        {

            /*
            start_time = os::get_milliseconds_since_epoch();
            for (auto &it : rand_vec)
            {// 插入
                st2.insert(it);
            }
            start_time = os::get_milliseconds_since_epoch();
            */
            /*
            for (auto &it : rand_vec)
            {// 查询
                if (st2.end() == st2.find(it))
                {
                    std::cout << "error: find" << std::endl;
                    return;
                }
            }
            
            start_time = os::get_milliseconds_since_epoch();
            for (auto &it : rand_vec)
            {// 删除
                st2.erase(it);
            }
            end_time = os::get_milliseconds_since_epoch();
            x2 = end_time - start_time;
            std::cout << "std::set op used: " << x2 << " ms" << std::endl;
            st2.clear();
            */
        }
        {
            start_time = os::get_milliseconds_since_epoch();
            /*
            for (auto &it : rand_vec)
            {// 插入
                st.insert(it);
            }
            */
            for (auto &it: rand_vec)
            {
                test_vec.emplace_back(it);
            }


            /*
            start_time = os::get_milliseconds_since_epoch();
            */
            /*
            for (auto &it : rand_vec)
            {// 查询
                if (st.end() == st.find(it))
                {
                    std::cout << "error: find" << std::endl;
                    return;
                }
            }
            
            start_time = os::get_milliseconds_since_epoch();
            for (auto &it : rand_vec)
            {// 删除
                st.erase(it);
            }
            */
            end_time = os::get_milliseconds_since_epoch();
            x1 = end_time - start_time;
            res += x1;
            std::cout << "my RBTree op used: " << x1 << " ms" << std::endl;
            // st.clear();
            test_vec.clear();
        }
        
        // std::cout << "diff: " << (int32_t)(x1 - x2) << " ms" << std::endl;
        if (false)
        {
            for (auto &it : rand_vec)
            {
                st3.add(it, it);
            }
            /*
            for (auto &it : rand_vec)
            {
                if (!st3.exist(it))
                {
                    std::cout << "error: find" << std::endl;
                    return 0;
                }
            }
            */
            start_time = os::get_milliseconds_since_epoch();
            for (auto &it : rand_vec)
            {
                st3.del(it);
            }
            end_time = os::get_milliseconds_since_epoch();
            auto x3 = end_time - start_time;
            std::cout << "other rb_tree insert used: " << x3 << " ms" << std::endl;
            st3.clear();
        }

        std::cout << "==========================" << std::endl;
    }
    std::cout << "result=" << res << "ms" << std::endl;

}

template<typename T>
void TestC::test_tmp(const T &t)
{
    std::cout << t << std::endl;
}

void TestC::test_foreach()
{
    auto someFunction = [](int &i) {
        std::cout << "#i=" << i << std::endl;
    };
    std::vector<std::thread> v;
    for (int i = 0; i < 10; ++i)
    {
        v.emplace_back(someFunction, std::ref(i));
    }
    std::cout << "emplace done" << std::endl;
    std::for_each(std::begin(v), std::end(v), std::mem_fn(&std::thread::join));
    std::cout << "join done" << std::endl;
}
#endif 